
#include "glsprites.h"
#include "math.h"
#include <iostream>

#include <QKeyEvent>
#include <QBitmap>
#include <QMessageBox>

GLWidget::GLWidget() : QGLWidget()
{
    mouseLocked = false;

    gameState = 2;
    stateSelection[0] = 0;
    stateSelection[1] = 4;
    gameType = 0;
    gamePlayers = 0;

    font = QFont("Verdana", 20, 0, 0 );

    // pagrindinis meniu
    txt[0].append( TMLabel(QString::fromStdWString(L"Biliardas"), 300, 50, font, -1 ) );
    myg[0].append( TMLabel(QString::fromStdWString(L"Naujas žaidimas"), 300, 100, font, 0 ) );
    myg[0].append( TMLabel(QString::fromStdWString(L"Tęsti žaidimą"), 300, 150, font, 1) );
    myg[0].append( TMLabel(QString::fromStdWString(L"Nustatymai"), 300, 200, font, 2) );
    myg[0].append( TMLabel(QString::fromStdWString(L"Baigti"), 300, 250, font, 3) );

    // Naujas žaidimas
    gameTypeStrings[0] = QString::fromStdWString(L"Pulas 8");
    gameTypeStrings[1] = QString::fromStdWString(L"Pulas 9");

    gamePlayersStrings[0] = QString::fromStdWString(L"1P vs 2P");
    gamePlayersStrings[1] = QString::fromStdWString(L"1P vs AI");

    txt[1].append( TMLabel(QString::fromStdWString(L"Naujas žaidimas"), 300, 50, font, -1));
    txt[1].append( TMLabel(QString::fromStdWString(L"Žaidimo tipas:"), 300, 100, font, -1));
    txt[1].append( TMLabel(QString::fromStdWString(L"Žaidėjai:"), 300, 150, font, -1));
    myg[1].append( TMLabel(QString::fromStdWString(L"<"), txt[1][1].x2+10, 100, font, 0));
    myg[1].append( TMLabel(QString::fromStdWString(L">"), txt[1][1].x2+200, 100, font, 1));
    myg[1].append( TMLabel(QString::fromStdWString(L"<"), txt[1][2].x2+10, 150, font, 2));
    myg[1].append( TMLabel(QString::fromStdWString(L">"), txt[1][2].x2+200, 150, font, 3));
    myg[1].append( TMLabel(QString::fromStdWString(L"Žaisti"), 300, 200, font, 4));
    myg[1].append( TMLabel(QString::fromStdWString(L"Grįžti"), 300, 250, font, 5));

    // žaidimo pauzė
    txt[2].append( TMLabel(QString::fromStdWString(L"Pauzė"), 300, 100, font, -1));
    myg[2].append( TMLabel(QString::fromStdWString(L"Nustatymai"), 300, 200, font, 0));
    myg[2].append( TMLabel(QString::fromStdWString(L"Išsaugoti žaidimą"), 300, 250, font, 1));
    myg[2].append( TMLabel(QString::fromStdWString(L"Pagabla"), 300, 300, font, 2));
    myg[2].append( TMLabel(QString::fromStdWString(L"Baigti žaidimą"), 300, 350, font, 3));
    myg[2].append( TMLabel(QString::fromStdWString(L"Grįžti į žaidimą"), 300, 400, font, 4));

    TBall ball = { CVect2d( 240.0, 300.0 ), CVect2d( 0.0, 0.0 ), 9.0, 1.0f, 1.0f, 1.0f, false };
    balls.append( ball );
    ball.pos.set( 545.0, 300.0 ); balls.append( ball );
    ball.pos.set( 560.0, 290.0 ); balls.append( ball );
    ball.pos.set( 560.0, 310.0 ); balls.append( ball );
    ball.pos.set( 575.0, 280.0 ); balls.append( ball );
    ball.pos.set( 575.0, 300.0 ); balls.append( ball );
    ball.pos.set( 575.0, 320.0 ); balls.append( ball );
    ball.pos.set( 590.0, 270.0 ); balls.append( ball );
    ball.pos.set( 590.0, 290.0 ); balls.append( ball );
    ball.pos.set( 590.0, 310.0 ); balls.append( ball );
    ball.pos.set( 590.0, 330.0 ); balls.append( ball );
    ball.pos.set( 605.0, 260.0 ); balls.append( ball );
    ball.pos.set( 605.0, 280.0 ); balls.append( ball );
    ball.pos.set( 605.0, 300.0 ); balls.append( ball );
    ball.pos.set( 605.0, 320.0 ); balls.append( ball );
    ball.pos.set( 605.0, 340.0 ); balls.append( ball );

    arr[0].r = arr[0].g = arr[0].b = 1.0f;

    TBox box = { CVect2d( 0.0, 0.0), CVect2d( 0.0, 0.0 ), 1.0f, 1.0f, 1.0f };

    int width = 800, height = 600;
    box.pos.set( -9, height/2); box.hsize.set( 10, height/2);
    boxes.append( box );
    box.pos.set( width/2, -10 ); box.hsize.set( width/2, 10 );
    boxes.append( box );
    box.pos.set( width+10, height/2); box.hsize.set( 10, height/2);
    boxes.append( box );
    box.pos.set( width/2, height+9 ); box.hsize.set( width/2, 10 );
    boxes.append( box );
    // 50, 107

    box.pos.set( 247, 127 ); box.hsize.set( 133, 20 ); boxes.append( box );
    box.pos.set( 553, 127 ); box.hsize.set( 133, 20 ); boxes.append( box );
    box.pos.set( 247, 473 ); box.hsize.set( 133, 20 ); boxes.append( box );
    box.pos.set( 553, 473 ); box.hsize.set( 133, 20 ); boxes.append( box );
    box.pos.set( 72, 300 ); box.hsize.set( 22, 129 ); boxes.append( box );
    box.pos.set( 728, 300 ); box.hsize.set( 22, 129 ); boxes.append( box );

    TTriangle trng = { {CVect2d(0.0, 0.0), CVect2d(0.0, 0.0), CVect2d(0.0, 0.0)}, 1.0f, 1.0f, 1.0f  };
    trng.p[0].set( 50, 171 ); trng.p[1].set( 94, 171 ); trng.p[2].set( 50, 117 ); tngs.append( trng );
    trng.p[0].set( 65, 107 ); trng.p[1].set( 114, 147 ); trng.p[2].set( 114, 107 ); tngs.append( trng );
    trng.p[0].set( 380, 147 ); trng.p[1].set( 395, 107 ); trng.p[2].set( 380, 107 ); tngs.append( trng );
    trng.p[0].set( 420, 147 ); trng.p[1].set( 420, 107 ); trng.p[2].set( 405, 107 ); tngs.append( trng );
    trng.p[0].set( 686, 147 ); trng.p[1].set( 735, 107 ); trng.p[2].set( 686, 107 ); tngs.append( trng );
    trng.p[0].set( 750, 171 ); trng.p[1].set( 750, 117 ); trng.p[2].set( 706, 171 ); tngs.append( trng );

    trng.p[0].set( 50, 483 ); trng.p[1].set( 94, 429 ); trng.p[2].set( 50, 429 ); tngs.append( trng );
    trng.p[0].set( 65, 493 ); trng.p[1].set( 114, 493 ); trng.p[2].set( 114, 453 ); tngs.append( trng );
    trng.p[0].set( 380, 493 ); trng.p[1].set( 395, 493 ); trng.p[2].set( 380, 453 ); tngs.append( trng );
    trng.p[0].set( 405, 493 ); trng.p[1].set( 420, 493 ); trng.p[2].set( 420, 453 ); tngs.append( trng );
    trng.p[0].set( 686, 493 ); trng.p[1].set( 735, 493 ); trng.p[2].set( 686, 453 ); tngs.append( trng );    
    trng.p[0].set( 750, 483 ); trng.p[1].set( 750, 429 ); trng.p[2].set( 706, 429 ); tngs.append( trng );

    TBall h = { CVect2d( 0.0, 0.0 ), CVect2d( 0.0, 0.0 ), 20.0, 1.0f, 1.0f, 1.0f, false };
    h.pos.set( 83, 136 ); holes.append( h );
    h.pos.set( 400, 127 ); holes.append( h );
    h.pos.set( 717, 136 ); holes.append( h );    
    h.pos.set( 83, 464 ); holes.append( h );
    h.pos.set( 400, 473 ); holes.append( h );
    h.pos.set( 717, 464 ); holes.append( h );


}

GLWidget::~GLWidget()
{
}

// GL inicijavimo metodas
void GLWidget::initializeGL()
{    
    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    texture[0] = bindTexture(QPixmap(QString(":/img/MAX0010.jpg")), GL_TEXTURE_2D);
    texture[1] = bindTexture(QPixmap(QString(":/img/all.PNG")), GL_TEXTURE_2D);
    texture[2] = bindTexture(QPixmap(QString(":/img/teksturos.png")), GL_TEXTURE_2D);
    texture[3] = bindTexture(QPixmap(QString(":/img/stalas.png")), GL_TEXTURE_2D);

    glEnable(GL_TEXTURE_2D);
    glColor4f(1.0f,1.0f,1.0f,1.0f);
    glEnable(GL_BLEND);
    glEnable(GL_ALPHA_TEST);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glAlphaFunc(GL_GREATER,0.1f);

}

// GL lango dydžio keitimo metodas,
// w - naujas lango plotis,
// h - naujas lango aukštis,
void GLWidget::resizeGL(int w, int h)
{
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,w,0,h,-100,100);
    glMatrixMode(GL_MODELVIEW);
    glClearColor(0.0f,0.0f,0.0f,1.0f);
}

// GL kadro piešimo metodas
void GLWidget::paintGL()
{    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glColor3f(1.0f, 1.0f, 1.0f );
    glBindTexture(GL_TEXTURE_2D,texture[0]);
    glBegin(GL_QUADS);  // fonas
        glTexCoord2f(0.0f,0.0f); glVertex3i(  0, 0,-100);
        glTexCoord2f(0.0f,1.0f); glVertex3i(  0, 600,-100);
        glTexCoord2f(1.0f,1.0f); glVertex3i(800, 600,-100);
        glTexCoord2f(1.0f,0.0f); glVertex3i(800, 0,-100);
    glEnd();

    glLoadIdentity();

    static float pulse = 0.0f;
    pulse += 0.1f;
    float in = 0.5f; //0.75f + sin( pulse )/8.0f;

    if ( gameState == 0 ) { // Pagrindinis meniu

        glColor3f(1.0f, 1.0f, 1.0f );
        foreach ( TMLabel l, txt[0] ) {
            renderText( l.x, l.y, l.text, font );
        }
        foreach ( TMLabel l, myg[0] ) {
            if ( stateSelection[0] == l.action ) glColor3f(in, in, in ); else glColor3f(1.0f, 1.0f, 1.0f );
            renderText( l.x, l.y, l.text, font );
        }

    } else if ( gameState == 1 ) {  // Naujas žaidimas
        glColor3f(1.0f, 1.0f, 1.0f );
        foreach ( TMLabel l, txt[1] )
            renderText( l.x, l.y, l.text, font );
        renderText( txt[1][1].x2 + 40, 100, gameTypeStrings[gameType], font );
        renderText( txt[1][2].x2 + 40, 150, gamePlayersStrings[gamePlayers], font );
        foreach ( TMLabel l, myg[1] ) {
            if ( stateSelection[1] == l.action ) glColor3f(in, in, in ); else glColor3f(1.0f, 1.0f, 1.0f );
            renderText( l.x, l.y, l.text, font );
        }
    } else if ( gameState == 2 || gameState == 4 ) {  // Žaidimo stadija arba žaidimo pauzė

        renderGameState();  // žaidimas renderinamas kitoje funkcijoje

        if ( gameState == 4 ) { // žaidimo pauzė
            glDisable(GL_TEXTURE_2D);       // piešiamas pusiau permatomas juodas ekranas
            glColor4f(0.0f, 0.0f, 0.0f, 0.5f );
            glBegin(GL_QUADS);  // fonas
                glVertex3i(  0, 0,-100);
                glVertex3i(  0, 600,-100);
                glVertex3i(800, 600,-100);
                glVertex3i(800, 0,-100);
            glEnd();            
            glEnable(GL_TEXTURE_2D);
            
            glColor3f(1.0f, 1.0f, 1.0f );
            foreach ( TMLabel l, txt[2] ) { // tekstukai
                renderText( l.x, l.y, l.text, font );
            }
            foreach ( TMLabel l, myg[2] ) { // mygtukai
                if ( stateSelection[2] == l.action ) glColor3f(in, in, in ); else glColor3f(1.0f, 1.0f, 1.0f );
                renderText( l.x, l.y, l.text, font );
            }

        }
    } else {
        glColor3f(1.0f, 1.0f, 1.0f );
        this->renderText( 10, 50, QString::fromStdWString(L"Nežinomas game state: ") + QString::number(gameState), font );
    }

    glFlush();

}

// metodas pagrindinei žaidimo logikai apdoroti
// return - grąžina 0 sekmingo vykdymo metu, -1 programos baigiui
int GLWidget::doLogic()
{
    if ( gameState == -1 ) {
        return -1;

    } else if ( gameState == 0 || gameState == 1 ) {    // main meniu arba naujas žaidimas
        int action = -1;

        if ( Kl.contains(Qt::Key_Return) )    // Enter
            action = stateSelection[gameState];  

        if ( Ml.contains(Qt::LeftButton) )    // pelės paspaudimas
            foreach ( TMLabel l, myg[gameState] )
                if ( l.x < Mx && Mx < l.x2 && l.y2+10 < My && My < l.y+10 )
                    action = l.action;

        if ( Mdx != 0 || Mdy != 0 )           // pelės žymėjimas
            foreach ( TMLabel l, myg[gameState] )
                if ( l.x < Mx && Mx < l.x2 && l.y2+10 < My && My < l.y+10 )
                    stateSelection[gameState] = l.action;

        if( Kl.contains(Qt::Key_Down) && stateSelection[gameState] < myg[gameState].size()-1 ) {  //  žymėjimas klaviatūra
            stateSelection[gameState]++;
        } else if( Kl.contains(Qt::Key_Up) && stateSelection[gameState] > 0 ) {
            stateSelection[gameState]--;
        }

        if ( gameState == 0 ) { // pagrindinis meniu
            if ( Kl.contains(Qt::Key_Escape) )
                action = 3; // Baigti žaidimą
            if ( action == 0 ) {    // Naujas žaidimas
                gameState = 1;
            } else if ( action == 1 ) { // Tęsti žaidimą
                QMessageBox::information( 0, QString::fromStdWString(L"Klaida"),
                                          QString::fromStdWString(L"Žaidimo tesimo funkcija dar nėra sukurta") );
            } else if ( action == 2 ) { // Nustatymai
                QMessageBox::information( 0, QString::fromStdWString(L"Klaida"),
                                          QString::fromStdWString(L"Nustatymų stadija dar nėra sukurta") );
            } else if ( action == 3 ) { // Baigti
                gameState = -1;
            }
        } else if ( gameState == 1 ) {  // naujas žaidimas
            if ( Kl.contains(Qt::Key_Escape) )
                action = 5; // grįžti į pagrindinį meniu
            if ( action == 0 ) {    // "<" žaidimo tipas
                if ( gameType > 0 )
                    gameType--;
            } else if ( action == 1 ) { // ">" žaidimo tipas
                if ( gameType < 1 )
                    gameType++;
            } else if ( action == 2 ) { // "<" žaidėjų tipas
                if ( gamePlayers > 0 )
                    gamePlayers--;
            } else if ( action == 3 ) { // ">" žaidėjų tipas
                if ( gamePlayers < 1 )
                    gamePlayers++;
            } else if ( action == 4 ) { // pradėti žaidimą
                gameState = 2;
            } else if ( action == 5 ) { // Grįžti
                gameState = 0;
            }
        }
    } else if ( gameState == 2 ) {  // pargindinė žaidimo stadija
        doGameStateLogic();

    } else if ( gameState == 4 ) {  // žaidimo pauzė
        int action = -1;

        if  ( Kl.contains(Qt::Key_Escape) )
            action = 4;  // grąžina į žaidimą
        if ( Kl.contains(Qt::Key_Return) )    // Enter
            action = stateSelection[2];

        if ( Ml.contains(Qt::LeftButton) )    // pelės paspaudimas
            foreach ( TMLabel l, myg[2] )
                if ( l.x < Mx && Mx < l.x2 && l.y2+10 < My && My < l.y+10 )
                    action = l.action;

        if ( Mdx != 0 || Mdy != 0 )           // pelės žymėjimas
            foreach ( TMLabel l, myg[2] )
                if ( l.x < Mx && Mx < l.x2 && l.y2+10 < My && My < l.y+10 )
                    stateSelection[2] = l.action;

        if( Kl.contains(Qt::Key_Down) && stateSelection[2] < myg[2].size()-1 ) {  //  žymėjimas klaviatūra
            stateSelection[2]++;
        } else if( Kl.contains(Qt::Key_Up) && stateSelection[2] > 0 ) {
            stateSelection[2]--;
        }

        if ( action == 0 ) {    // Nustatymai
            QMessageBox::information( 0, QString::fromStdWString(L"Klaida"),
                                      QString::fromStdWString(L"Nusatymų stadija dar nėra sukurta") );
        } else if ( action == 1 ) { // Išsaugoti žaidimą
            QMessageBox::information( 0, QString::fromStdWString(L"Klaida"),
                                      QString::fromStdWString(L"Žaidimo saugojimo funkcija dar nėra sukurta") );
        } else if ( action == 2 ) { // Pagalba
            QMessageBox::information( 0, QString::fromStdWString(L"Klaida"),
                                      QString::fromStdWString(L"Pagalbos stadija dar nėra sukurta") );
        } else if ( action == 3 ) { // Baigti žaidimą
            gameState = 0;
        } else if ( action == 4 ) { // Grįžti į žaidimą
            gameState = 2;
        }

    } else {
        if  ( Kl.contains(Qt::Key_Escape) )
            gameState = 0;  // grąžina į pagrindinį meniu
    }

    return 0;
}

// metodas priima mygtukų paspaudimo komandas ir jas sukelia į sąrašus
// e - QKeyEventas, informacija apie paspaustą/atspaustą mygtuką
// isPressed - ar mygtukas paspaustas
void GLWidget::handleKeys(QKeyEvent* e, bool isPressed)
{
    // mygtukų būsenos surašomos į hash lentelę
    if ( Kh.contains(e->key()) ) {   // hash table
        Kh[e->key()] = isPressed;
    } else {
        Kh.insert( e->key(), isPressed );
    }

    // visi paspausti mygtukai renkami į eilę, kad būtu apdoroti sekančio kadro metu
    if ( isPressed )
        Kq.enqueue( e->key() );
}

void GLWidget::mousePressEvent(QMouseEvent* e)
{
    Mh[e->button()] = true;
    Mq.enqueue( e->button() );
}

void GLWidget::mouseMoveEvent(QMouseEvent* e)
{
    move = true;
}

void GLWidget::mouseReleaseEvent(QMouseEvent* e)
{
    Mh[e->button()] = false;
    Mrq.enqueue( e->button() );
}

// metodas kviečiamas kai programos langas yra paslepiamas
void GLWidget::lostFocus()
{
    Mh.clear();
    Kh.clear();
    if ( gameState == 2 )
        gameState = 4;
}

// metodas tikrina pelės judėjimą, bei paruošia nuspaustų mygtukų eilę
void GLWidget::handleControls()
{
    static QPoint pos(QCursor::pos());
    static QPoint d;
    d = QCursor::pos() - pos;
    if ( mouseLocked )
        QCursor::setPos(500,400);   // "center" of the screen
    pos = QCursor::pos();
    Mdx = d.x();
    Mdy = d.y();

    QPoint p = this->mapFromGlobal(QCursor::pos());
    Mx = p.x();
    My = p.y();

    Ml.clear();
    while(!Mq.isEmpty())
        Ml.append(Mq.dequeue());
    Mrl.clear();
    while(!Mrq.isEmpty())
        Mrl.append(Mrq.dequeue());

    Kl.clear();
    while (!Kq.isEmpty())
        Kl.append(Kq.dequeue());
}

// Metodas "užrakiną" pelę kad jos judėjimą gautu tik GL langas
void GLWidget::lockMouse()
{
    static QBitmap cur(16,16);
    cur.clear();
    QCursor::setPos(500,400);
    mouseLocked = true;
    this->grabMouse( QCursor(cur, cur, 0, 0) );
}

// metodas "atrakina" pelę
void GLWidget::unlockMouse()
{
    mouseLocked = false;
    this->releaseMouse();
}

// Rodiklytės piešimo metodas
void GLWidget::drawArrow( const TArrow &a ) {
    glColor3f( a.r, a.g, a.b );
    glDisable( GL_TEXTURE_2D );
    glBegin( GL_LINES );
        CVect2d tip = a.pos+a.dir;
        glVertex2i( a.pos.getX(), height()-a.pos.getY() ); glVertex2i( tip.getX(), height()-tip.getY() );
        if ( a.dir > 0.0001 ) {
            CVect2d lf = (a.dir * -1.0).direction() * 5.0;
            CVect2d rf = tip + lf + lf.rightNormal();
            lf = tip + lf + lf.leftNormal();
            glVertex2i( tip.getX(), height()-tip.getY() ); glVertex2i( lf.getX(), height()-lf.getY() );
            glVertex2i( tip.getX(), height()-tip.getY() ); glVertex2i( rf.getX(), height()-rf.getY() );
        }
    glEnd();
    glEnable( GL_TEXTURE_2D );
}

// Trikampių piešimo metodas
void GLWidget::drawTriangle( const TTriangle &t ) {
    glColor3f( t.r, t.g, t.b );
    glDisable( GL_TEXTURE_2D );
    glBegin( GL_LINE_LOOP );
        glVertex2i( t.p[0].getX(), height()-t.p[0].getY() );
        glVertex2i( t.p[1].getX(), height()-t.p[1].getY() );
        glVertex2i( t.p[2].getX(), height()-t.p[2].getY() );
    glEnd();
    glEnable( GL_TEXTURE_2D );
}

// Apskritimų piešimo metodas
void GLWidget::drawCircle( const TBall &b ) {
    glColor3f( b.r, b.g, b.b );
    glDisable( GL_TEXTURE_2D );
    glBegin( GL_LINE_LOOP );
        int rounding = 60;
        for ( int i = 1; i <= rounding; i++ ) {
            glVertex2i( b.pos.getX() + sin(6.28318*i/rounding)*b.radius,
                        height()- b.pos.getY() - cos(6.28318*i/rounding)*b.radius );
        }
    glEnd();
    glEnable( GL_TEXTURE_2D );
}

// Stačiakampių piešimo metodas
void GLWidget::drawAABB( const TBox &b )
{
    glColor3f( b.r, b.g, b.b );
    glDisable( GL_TEXTURE_2D );
    glBegin( GL_LINE_LOOP );
        glVertex2i( b.pos.getX()-b.hsize.getX(), height()-(b.pos.getY()-b.hsize.getY()) );
        glVertex2i( b.pos.getX()-b.hsize.getX(), height()-(b.pos.getY()+b.hsize.getY()) );
        glVertex2i( b.pos.getX()+b.hsize.getX(), height()-(b.pos.getY()+b.hsize.getY()) );
        glVertex2i( b.pos.getX()+b.hsize.getX(), height()-(b.pos.getY()-b.hsize.getY()) );
   glEnd();
   glEnable( GL_TEXTURE_2D );
}

void GLWidget::drawBall( const CVect2d &pos, const double &radius, const int &ballN )
{
    glColor3f(1.0f, 1.0f, 1.0f );
    glBindTexture(GL_TEXTURE_2D,texture[2]);    // kamuoliukai
    glBegin(GL_QUADS);
        glTexCoord2f(ballN/16.0f,1.0f); glVertex3i( pos.getX()-radius, height()-pos.getY()-radius,-100);
        glTexCoord2f(ballN/16.0f,0.0f); glVertex3i( pos.getX()-radius, height()-pos.getY()+radius,-100);
        glTexCoord2f((ballN+1)/16.0f,0.0f); glVertex3i( pos.getX()+radius, height()-pos.getY()+radius,-100);
        glTexCoord2f((ballN+1)/16.0f,1.0f); glVertex3i( pos.getX()+radius, height()-pos.getY()-radius,-100);
    glEnd();
}

// motodas piešiantis žaidimo sceną
// Čia turėtu būti TIK piešimas! visa logika ir valdymas turi būti doGameStateLogic metode
void GLWidget::renderGameState()
{
    glColor3f(0.9f, 0.9f, 0.9f );
    renderText( 10, 50, QString::fromStdWString(L"Žaidimo stadija"), font );

    glColor3f(1.0f, 1.0f, 1.0f );
    glBindTexture(GL_TEXTURE_2D,texture[3]);    // stalas
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f,1.0f); glVertex3i(  50, height()-107,-100);
        glTexCoord2f(0.0f,0.0f); glVertex3i(  50, height()-493,-100);
        glTexCoord2f(1.0f,0.0f); glVertex3i(750, height()-493,-100);
        glTexCoord2f(1.0f,1.0f); glVertex3i(750, height()-107,-100);
    glEnd();

//    foreach ( TBox b, boxes )
//        drawAABB( b );
//    foreach ( TBall h, holes )
//        drawCircle( h );
//    foreach ( TTriangle t, tngs )
//        drawTriangle( t );
//    foreach ( TBall b, balls )
//        drawCircle( b );
    for ( int b = 0; b < balls.size(); b++ )
        if ( !balls[b].inHole )
            drawBall( balls[b].pos, balls[b].radius, b );

//    drawArrow(arr[0]);

}

// žaidimo stadijos logika ir valdymas
void GLWidget::doGameStateLogic()
{
    if  ( Kl.contains(Qt::Key_Escape) )
        gameState = 4;  // žaidimo pauzė

    // Kamuoliuko perstatymas į numatytąją poziciją
    if ( Kh[Qt::Key_Space] ) {
        balls[0].pos.set( 240.0, 300.0 );
        balls[0].speed.set( 0.0, 0.0 );
        balls[0].inHole = false;
    }

    // Greičio keitimas klaviatūra
    if ( Kh[Qt::Key_Left] )  balls[0].speed += CVect2d( -0.2, 0.0 );
    if ( Kh[Qt::Key_Right] ) balls[0].speed += CVect2d( 0.2, 0.0 );
    if ( Kh[Qt::Key_Down] )  balls[0].speed += CVect2d( 0.0, 0.2 );
    if ( Kh[Qt::Key_Up] )    balls[0].speed += CVect2d( 0.0, -0.2 );

   // Kamuoliuko "paleidimas"
    if ( Ml.contains(Qt::LeftButton) ) {
        balls[0].pos.set( Mx, My );
        balls[0].speed.set( 0.0, 0.0 );
        balls[0].inHole = false;
    }
    if ( Mrl.contains(Qt::LeftButton) )
        balls[0].speed = (CVect2d( Mx, My ) - balls[0].pos)/20;

    // Randa greičiausio kamuoliuko greitį
    double maxSpeed = 0.0;
    for ( int i = 0; i < balls.size(); i++ )
        if ( balls[i].speed > maxSpeed )
            maxSpeed = balls[i].speed.lenght();

    // Judėjimo skaidymas į smulesnius tarpus
    int repeat = (maxSpeed/(balls[0].radius/4.0));   // judėjimo skaldymas į tarpus
    if ( repeat < 1 )  repeat = 1;
    if ( repeat > 50 ) repeat = 50;

    for ( int b = 0; b < balls.size(); b++ )
        balls[b].speed /= repeat;

    for ( int b = 0; b < balls.size(); b++ ){
        if ( balls[b].inHole )
            continue;
        for ( int i = 0; i < repeat; i++ )
        {
            // Kamuoliuko pozicijos keitimas
            balls[b].pos += balls[b].speed;

            // tikrina susidurimus
            int n = balls.size();
            for ( int i = 0; i < n; i++ )
                if ( b != i )
                    if ( !balls[i].inHole )
                    elasticCollision( balls[b], balls[i] );

            for ( int i = 0; i < boxes.size(); i++ )
                pushOut( balls[b], boxes[i] );

            for ( int i = 0; i < tngs.size(); i++ )
                collide( balls[b], tngs[i] );\

            for ( int i = 0; i < holes.size(); i++ ) {
                if ( inHole( balls[b], holes[i] ) ) {
                    balls[b].speed.set( 0.0, 0.0 );
                    balls[b].inHole = true;
                }
            }
        }

        if ( balls[b].speed < 0.15 )    // Jei kamuoliukas per lėtas jis sustabdomas
            balls[b].speed.set( 0.0, 0.0 );
        else
            balls[b].speed += balls[b].speed.direction() * -1 * 0.018;  // Kamuoliuko lėtinimas
    }

    for ( int b = 0; b < balls.size(); b++ )
        balls[b].speed *= repeat;

    arr[0].dir = balls[0].speed * 10 / repeat;
    arr[0].pos = balls[0].pos;

}
